import { createAlova, RequestBody } from 'alova';
import adapterFetch from 'alova/fetch';
import ReactHook from 'alova/react';

import { loginSsoLogoutInfo } from '@/api/login';
import { mapStg } from '@/utils/storage';

/**
 * 统一的API响应接口
 */
export interface ApiResponse<T = any> {
	/**
	 * 响应数据
	 */
	data: T;

	/**
	 * 错误码
	 */
	errorCode: number;

	/**
	 * 错误信息
	 */
	errorMsg: string;

	/**
	 * 请求是否成功
	 */
	success: boolean;

	/**
	 * 时间戳
	 */
	timestamp: number;
	[key: string]: any;
}

/** 白名单 - 不需要验证 token 的接口 */
const whiteList = [
	'/login',
	'/register',
	'/forgot-password',
	'/refresh-token',
	'/file/upload',
	'/api/upload',
	'/file/preview'
];

const showLog = false;

/** HTTP 状态码常量 */
const HTTP_STATUS = {
	OK: 200,
	UNAUTHORIZED: 401,
	FORBIDDEN: 403,
	NOT_FOUND: 404,
	INTERNAL_SERVER_ERROR: 500
} as const;

/** 业务状态码常量 */
const BUSINESS_CODE = {
	SUCCESS: 200,
	UNAUTHORIZED: 401,
	TOKEN_EXPIRED: 402,
	FORBIDDEN: 403
} as const;

/** Loading 管理器 */
class LoadingManager {
	private static instance: LoadingManager;
	private loadingCount = 0;
	private loadingTimer: NodeJS.Timeout | null = null;

	static getInstance(): LoadingManager {
		if (!LoadingManager.instance) {
			LoadingManager.instance = new LoadingManager();
		}
		return LoadingManager.instance;
	}

	/** 显示 loading */
	showLoading(delay = 200): void {
		this.loadingCount++;

		// 防抖处理，避免快速请求时的闪烁
		if (this.loadingTimer) {
			clearTimeout(this.loadingTimer);
		}

		this.loadingTimer = setTimeout(() => {
			if (this.loadingCount > 0 && window.$loading?.show) {
				window.$loading.show();
			}
		}, delay);
	}

	/** 隐藏 loading */
	hideLoading(): void {
		this.loadingCount = Math.max(0, this.loadingCount - 1);

		if (this.loadingCount === 0) {
			if (this.loadingTimer) {
				clearTimeout(this.loadingTimer);
				this.loadingTimer = null;
			}

			if (window.$loading?.hide) {
				window.$loading.hide();
			}
		}
	}

	/** 强制隐藏 loading */
	forceHide(): void {
		this.loadingCount = 0;
		if (this.loadingTimer) {
			clearTimeout(this.loadingTimer);
			this.loadingTimer = null;
		}
		if (window.$loading?.hide) {
			window.$loading.hide();
		}
	}

	/** 获取当前loading状态 */
	get isLoading(): boolean {
		return this.loadingCount > 0;
	}
}

const loadingManager = LoadingManager.getInstance();

/** 检查是否在白名单中 */
const isInWhiteList = (url: string): boolean => {
	return whiteList.some(path => url.includes(path));
};

/** 处理 token 过期 */
const handleTokenExpired = (): void => {
	// 避免重复弹窗
	if (window.__tokenExpiredModalShown) {
		return;
	}
	window.__tokenExpiredModalShown = true;

	// 先强制隐藏所有loading
	loadingManager.forceHide();

	if (window.$modal?.info) {
		window.$modal.info({
			title: '登录状态已过期',
			content: '您的登录状态已过期，请重新登录以继续使用',
			okText: '重新登录',
			cancelText: '取消',
			maskClosable: false,
			onOk: () => {
				loginSsoLogoutInfo();
				mapStg.remove('token');
				mapStg.remove('userInfo');
				mapStg.remove('isLogin');
				window.__tokenExpiredModalShown = false;
				// 使用 replace 避免回退到需要登录的页面
				// window.location.replace('#/login');
			},
			onCancel: () => {
				window.__tokenExpiredModalShown = false;
			}
		});
	} else {
		// 如果没有modal组件，直接跳转
		console.warn('$modal not available, redirecting to login');
		mapStg.remove('token');
		mapStg.remove('userInfo');
		window.__tokenExpiredModalShown = false;
		window.location.replace(`#${import.meta.env.VITE_HOME_URL ?? '/login'}`);
	}
};

/** 显示错误消息 */
const showErrorMessage = (msg: string, isShowMsg = true): void => {
	console.log('[ msg ] >', msg);
	if (window.$message?.error && isShowMsg) {
		window.$message.destroy();
		window.$message.error(msg ?? '服务异常，请稍后重试');
	} else {
		console.error('API Error:', msg);
		// 可以在这里添加其他错误提示方式，比如toast
	}
};

/** 需要跳过loading的路径 */
const skipLoadingPaths = ['/heartbeat', '/ping', '/health'];

const fetchClient = createAlova({
	baseURL: import.meta.env.VITE_BASE_API,
	timeout: 300 * 1000,
	statesHook: ReactHook,
	requestAdapter: adapterFetch(),

	beforeRequest: method => {
		// 自动显示 loading（跳过某些不需要 loading 的请求）
		const shouldShowLoading = !skipLoadingPaths.some(path => method.url.includes(path));

		if (shouldShowLoading) {
			// 检查是否禁用自动 loading
			const disableLoading =
				method.meta?.disableLoading ?? method.config.headers?.['X-Disable-Loading'] === 'true';

			if (!disableLoading) {
				loadingManager.showLoading();
			}
		}
		if (method.meta?.baseURL) {
			method.baseURL = method.meta.baseURL;
		}
		// console.log('method.config.headers', method.url);
		// 设置默认请求头
		method.config.headers = {
			// 'Content-Type': 'application/json',
			...method.config.headers
		};
		const token = mapStg.get('token', '');
		if (token) {
			method.config.headers['Authorization'] = `Bearer ${token}`;
		}
		loadingManager.hideLoading();
		// 检查是否需要添加 token
		if (!method.meta?.auth && !isInWhiteList(method.url)) {
			if (!token) {
				// 隐藏 loading
				// 对于需要 token 但没有 token 的请求，直接处理登录过期
				handleTokenExpired();
				throw new Error('Token not found'); // 使用 throw 而不是 Promise.reject
			}
		}

		// 开发环境下打印请求信息
		if (import.meta.env.DEV && showLog) {
			console.log(`🚀 API Request: ${method.type} ${method.url}`, {
				headers: method.config.headers,
				data: method.data
			});
		}
	},

	responded: {
		onSuccess: async (response, method) => {
			// 隐藏 loading
			loadingManager.hideLoading();
			let isShowMsg = true;
			try {
				const dataJSON = await response.json();
				// 开发环境下打印响应信息
				if (import.meta.env.DEV && showLog) {
					console.log(`✅ API Response: ${method.type} ${method.url}`, dataJSON);
				}

				// 检查响应数据结构
				if (!dataJSON) {
					console.warn('Response data is empty:', response);
					return response;
				}
				const { errorCode, errorMsg } = dataJSON;

				if (
					method.url.includes('/sso/getRedirectUrl') ||
					method.url.includes('/api/recognize') ||
					method.url.includes('/user/checkEnterpriseAdmin')
				) {
					isShowMsg = false;
				}
				// 如果没有code字段，可能是直接返回数据的接口
				if (errorCode === undefined) {
					return dataJSON;
				}

				// 处理不同的业务状态码
				switch (errorCode) {
					case BUSINESS_CODE.SUCCESS:
						return dataJSON;

					case BUSINESS_CODE.UNAUTHORIZED:
					case BUSINESS_CODE.TOKEN_EXPIRED:
						handleTokenExpired();
						showErrorMessage(errorMsg ?? '权限不足', isShowMsg);
						throw new Error(errorMsg ?? '登录已过期');

					case BUSINESS_CODE.FORBIDDEN:
						showErrorMessage(errorMsg ?? '权限不足', isShowMsg);
						throw new Error(errorMsg ?? '权限不足');

					default:
						showErrorMessage(errorMsg ?? '请求失败', isShowMsg);
						throw new Error(errorMsg ?? '请求失败');
				}
			} catch (error: any) {
				// 处理错误
				showErrorMessage(error.message ?? '服务异常');
			}
		},

		onError: (error, method) => {
			// 隐藏 loading
			loadingManager.hideLoading();

			// 开发环境下打印错误信息
			if (import.meta.env.DEV && showLog) {
				console.error(`❌ API Error: ${method.type} ${method.url}`, error);
			}

			const { response } = error;
			let errorMessage = '网络请求失败';

			if (response) {
				const { status, statusText } = response;

				// 处理不同的 HTTP 状态码
				switch (status) {
					case HTTP_STATUS.UNAUTHORIZED:
						handleTokenExpired();
						errorMessage = '登录已过期';
						break;

					case HTTP_STATUS.FORBIDDEN:
						errorMessage = '权限不足';
						break;

					case HTTP_STATUS.NOT_FOUND:
						errorMessage = '接口不存在';
						break;

					case HTTP_STATUS.INTERNAL_SERVER_ERROR:
						errorMessage = '服务器内部错误';
						break;

					default:
						try {
							// 尝试解析错误响应
							const errorData = response.data;
							errorMessage = errorData?.message || statusText || `请求失败 (${status})`;
						} catch {
							errorMessage = statusText || `请求失败 (${status})`;
						}
				}
			} else if (error.name === 'AbortError') {
				errorMessage = '请求已取消';
				// 请求取消时不显示错误消息
				return Promise.reject(error);
			} else if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
				errorMessage = '请求超时，请稍后重试';
			} else if (!navigator.onLine) {
				errorMessage = '网络连接失败，请检查网络设置';
			}

			showErrorMessage(errorMessage);
			return Promise.reject(error);
		}
	}
});

export function apiGet<T = unknown>(url: string, config = {}) {
	return fetchClient.Get<ApiResponse<T>>(url, config);
}

export function apiPost<T = unknown>(url: string, data: RequestBody, config = {}) {
	return fetchClient.Post<ApiResponse<T>>(url, data, config);
}

export function apiPut<T = unknown>(url: string, data: RequestBody, config = {}) {
	return fetchClient.Put<ApiResponse<T>>(url, data, config);
}

export function apiDelete<T = unknown>(url: string, config = {}) {
	return fetchClient.Delete<ApiResponse<T>>(url, config);
}
const apiClient = {
	Get: apiGet,
	Post: apiPost,
	Put: apiPut,
	Delete: apiDelete
};

// 导出 loading 管理器，供外部使用
export { loadingManager };
export default apiClient;
